package com.xyy.saas.payment.service.jd;

import com.alibaba.fastjson.JSON;
import com.xyy.saas.payment.service.impl.JDPayServiceImpl;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.jdpay.BASE64;
import com.xyy.saas.payment.util.jdpay.FileUtil;
import com.xyy.saas.payment.util.jdpay.MD5;
import com.xyy.saas.payment.util.jdpay.WebUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.text.ParseException;
import java.util.*;

public interface JDBillService {

    /**
     * 京东账单下载地址
     */
    String JD_BILL_DOWN_URL = "https://bapi.jdpay.com/api/download.do";
    Logger log = LoggerFactory.getLogger(JDBillService.class);

    /**
     * 京东绑卡支付二级平台商户号
     */
    String JD_PLAT_NO = "133400097004";
    /**
     * 京东绑卡支付二级分账商户号
     */
    String JD_ACCOUNT_NO = "133400097005";
    /**
     * 京东聚合支付二级平台商户号
     */
    String JD_AGGRATE_PLAT_NO = "135647451008";
    /**
     * 京东聚合支付二级分账商户号-北京药帮忙
     */
    String JD_AGGRATE_ACCOUNT_NO = "133400097006";
    /**
     * 京东聚合支付-支付宝-二级平台商户号
     */
    String JD_AGGRATE_ALIPAY_PLAT_NO = "133400097002";
    /**
     * 获取一级商户号
     */
    default String getOwner(String merchantNo) {
        if (Arrays.asList(JD_PLAT_NO, JD_ACCOUNT_NO, JD_AGGRATE_ACCOUNT_NO,JD_AGGRATE_ALIPAY_PLAT_NO).contains(merchantNo)) {
            return "133400097";
        }
        if (Arrays.asList(JD_AGGRATE_PLAT_NO).contains(merchantNo)) {
            return "135647451";
        }
        throw new RuntimeException("商户号" + merchantNo + "错误！");
    }

    /**
     * 下载并解析账单
     * shareAccountWater：新分账商户根据交易结算信息生成结算文件（分账子商户）
     */
    void downAndAnalysisBill(String logPrefix, String date) throws Exception;

    String checkBill(String date) throws Exception;
    /**
     * 删除数据
     * @param billType : 账单类型
     * @param fileName : 文件名称
     * @return 影响行数
     */
    int delete(String logPrefix, String billType, String fileName);

    /**
     * 批量插入数据
     * @param billType : 账单类型
     * @param records : 账单数据
     * @return 影响行数
     */
    int insertBatch(String logPrefix, String billType, List<Object> records);

    /**
     * 填充信息：填充 商户编码、商户名称、客户名称、药帮忙订单号
     */
    void fillParam(String logPrefix, String billType, List<Object> records);

    /**
     * 账单解析
     * @param billType   : 账单类型
     * @param owner      : 一级商户号
     * @param merchantNo : 二级商户号
     * @param fileName   : 文件名称
     * @param billDate   : 账单日期
     * @param line       : 账单数据
     * @return 解析后的实体类
     */
    Object parse(String logPrefix, String billType, String owner, String merchantNo, String fileName, String billDate, String line);

    /**
     * 对读到的账单数据做转换
     */
    default String transCol(String[] cols, int index){
        if (index >= cols.length || StringUtils.isBlank(cols[index])) {
            return "";
        }
        String msg = cols[index];
        if (msg.startsWith("\"") && !msg.contains("，") && msg.length() >= 2) {
            return msg.substring(1, msg.length() - 1).trim();
        }
        if (StringUtils.isBlank(msg) || !msg.startsWith("=\"")) {
            return msg.trim();
        }
        if (StringUtils.isBlank(msg) || msg.length() <= 3) {
            return "";
        }
        return msg.substring(2, msg.length() - 1).trim();
    }

    /**
     * 账单下载
     */
    default void download(String logPrefix, String owner, String merchantNo, String fileName, String path, String date) throws Exception {
        log.info("{} [jdPay] 账单处理: 账单下载开始 {} {} {} {}", logPrefix, owner, merchantNo, fileName, path);
        FileUtil.deleteFile(logPrefix, JDPayServiceImpl.getDownPath(date) + File.separator + fileName);
        FileUtil.deleteFile(logPrefix, JDPayServiceImpl.getDownPath(date) + File.separator + fileName.replace(".zip", ".csv"));
        String data = "{'name':'" + fileName + "','path':'" + path + "'}";
        log.info("{} [jdPay]账单下载：RequestUrl:{} data: {}", logPrefix, JD_BILL_DOWN_URL, data);
        data = BASE64.encode(data.getBytes());
        String md5 = MD5.md5(data, ApolloUtil.getProperty("jd.pay." + owner + ".md5BillKey"));
        Map<String, String> params = new HashMap<>();
        params.put("md5", md5);
        params.put("data", data);
        params.put("owner", owner);
        log.info("{} [jdPay]账单处理: 账单下载：RequestUrl:{} requestParams: {}", logPrefix, JD_BILL_DOWN_URL, JSON.toJSON(params));
        try {
            WebUtils.download(JD_BILL_DOWN_URL, params, 5000, 50000, JDPayServiceImpl.getDownPath(date) + fileName);
        } catch (Exception e) {
            if (e.getMessage().contains("请求文件无效-->")) {
                log.warn("{} [jdPay]账单处理: 下载账单异常{}-{}-{}-{}：{}", logPrefix, owner, merchantNo, fileName, params, e);
            } else {
                log.error("{} [jdPay]账单处理: 下载账单异常{}-{}-{}-{}：{}", logPrefix, owner, merchantNo, fileName, params, e);
                File file = new File(JDPayServiceImpl.getDownPath(date) + fileName);
                if (file.exists()) {
                    log.info("{} [jdPay]账单处理: 账单下载异常，删除账单文件：{}", logPrefix, file.getName());
                    file.delete();
                }
                throw e;
            }
        }
    }

    /**
     * 解析账单
     * @param billType : 账单类型
     * @param fileName : 文件名称
     */
    default void analysisBill(String logPrefix, String date, String owner, String merchantNo, String billType, String fileName) throws IOException {
        int delete = deleteByBatch(logPrefix, billType, fileName);
        log.info("{} [jdPay]账单处理: 账单解析：删除历史数据:fileName-{}, 影响行数-{} ", logPrefix, fileName, delete);
        JDBillService billService = JDPayServiceImpl.getBillService(billType);
        BufferedReader bufferedReader = null;
        try {
            String filePath = JDPayServiceImpl.getDownPath(date) + fileName.replace(".zip", ".csv");
            if (!new File(filePath).exists()) {
                log.info("{} [jdPay]账单处理: 账单解析：文件[{}]不存在，不进行解析处理", logPrefix, filePath);
                return;
            }
            int totalLine = 0;
            bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "GBK"));
            String line;
            List<Object> records = new ArrayList<>();
            int currLine = 0;
            while ((line = bufferedReader.readLine()) != null) {
                if (++currLine <= 1) {
                    continue;
                }
                Object object = billService.parse(logPrefix, billType, owner, merchantNo, fileName, date, line);
                if (null == object) {
                    continue;
                }
                records.add(object);
                totalLine = totalLine + 1;
                if (records.size() % 50 == 0) {
                    billService.insertBatch(logPrefix, billType, records);
                    records = new ArrayList<>();
                }
            }
            if (records.size() > 0) {
                billService.insertBatch(logPrefix, billType, records);
            }
            log.info("{} [jdPay]账单处理: downAndAnalysisBill#analy : 文件{} 解析行数{} ", logPrefix, fileName, totalLine);
        } catch (Exception e) {
            throw e;
        } finally {
            if (null != bufferedReader) {
                bufferedReader.close();
            }
        }
    }

    /**
     * 删除数据
     */
    default int deleteByBatch(String logPrefix, String billType, String fileName) {
        JDBillService billService = JDPayServiceImpl.getBillService(billType);
        int delete = billService.delete(logPrefix, billType, fileName);
        int total = delete;
        while (delete > 0) {
            delete = billService.delete(logPrefix, billType, fileName);
            total += delete;
        }
        return total;
    }

}
